﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using VSDBM.Code.functions;
using VSDBM.Code.dto;
using VSDBM.Code.dao;

public partial class Visual_CRUD_Sequence_ImportGenBank : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {

            FillOrganism();
        }
        
    }

    protected void FillOrganism()
    {
        DataSet ds = OrganismDAO.select("WHERE status=1", "ORDER BY name");
        //verifica erro na querry
        if (ds.Tables.Count == 0)
        {
            Exception ex = new Exception("Table not found!");
            throw ex;
        }
        //verifica se existem organismos cadastrados.
        else if (ds.Tables[0].Rows.Count == 0)
        {
            DataRow dr = ds.Tables[0].NewRow();
            ds.Tables[0].Rows.InsertAt(dr, 0);
            ds.Tables[0].Rows[0]["name"] = "NO ORGANISMS FOUND";
            ds.Tables[0].Rows[0]["id"] = "0";

        }
        //Insere os organismos no Dropdown List(ddOrganism).

        ddOrganism.DataSource = ds.Tables[0];
        ddOrganism.DataTextField = "name";
        ddOrganism.DataValueField = "id";
        ddOrganism.DataBind();

        ddOrganism.Visible = true;

    }
   
    protected void btnImportFiles_Click(object sender, EventArgs e)
    {
        int OrganismId = Convert.ToInt32(ddOrganism.SelectedValue);
        //Start importation.
        if (FileUpload.HasFile)
        {
            if (FileUpload.PostedFile.ContentType == "text/html")
            {
                
               
                
                try
                {
                    
                    VSDBM.Code.dto.User usuariologado = (VSDBM.Code.dto.User)HttpContext.Current.Session["usuariologado"];
                    String FileName = AppDomain.CurrentDomain.BaseDirectory + "pagf-" + Guid.NewGuid()+".bin";
                    FileUpload.SaveAs(FileName);
                    StreamReader reader = new StreamReader(FileName);
                    ParameterizedThreadStart Starter = new ParameterizedThreadStart(threadAddSequence);
                    Thread thread = new Thread(Starter);
                    List<Object> Listadeparametros = new List<object>();
                    String codeprepair = usuariologado.name ;
                    codeprepair += FileUpload.FileName.ToString();
                    int numero = new Random(FileUpload.PostedFile.ContentLength).Next();
                    codeprepair += numero.ToString();
                    String jobcode = Encryption.CalculateMD5Hash(codeprepair);
                    Listadeparametros.Add(reader);
                    Listadeparametros.Add(usuariologado);
                    Listadeparametros.Add(jobcode);
                    Listadeparametros.Add(OrganismId);
                    Listadeparametros.Add(FileName);
                    thread.Start(Listadeparametros);

                    //Envia mensagem de FIM.
                    HttpContext.Current.Session["done"] = "Process started. <br> We will send you a message when it finishes. <br><br> Job Code: " +jobcode + "<br>";
                    Response.Redirect("../../../Visual/Done/Done.aspx");
 
                }
                catch (ThreadAbortException ex1)
                {
                    // do nothing
                }
                catch (Exception ex)
                {
                    HttpContext.Current.Session["exception"] = ex.Message;
                    Response.Redirect("../../../Visual/Errors/error.aspx");
                }
                

            }
            else
            {
                HttpContext.Current.Session["exception"] = "The selected file is not an valid '.html' file. ";
                Response.Redirect("../../../Visual/Errors/error.aspx");
            }
        }
        else
        {
            HttpContext.Current.Session["exception"] = "ERROR: You Should select a file to upload";
            Response.Redirect("../../../Visual/Errors/error.aspx");

        }
    }

    public void threadAddSequence(Object Parametros)
    {
        System.DateTime Starttime = System.DateTime.Now;
        List<Object> Listadeparametros = Parametros as List<Object>;
        StreamReader reader = Listadeparametros[0] as StreamReader;
        VSDBM.Code.dto.User usuariologado = Listadeparametros[1] as VSDBM.Code.dto.User;
        String jobcode = Listadeparametros[2] as String;
        String textseq = "";
        int organismId = Convert.ToInt32(Listadeparametros[3]);
        String FileName = Listadeparametros[4] as String;
        List<String[]> report = new List<string[]>();
        int SequenceCount = 0;
        int ErrorCount = 0;
        String biggerAcession = "";
        int biggerSequence = 0;
        while (reader.EndOfStream == false)
        {
            String line = reader.ReadLine();
            if (!line.Equals("//"))
            {
                textseq += line + " \n ";
            }
            else
            {
                
                try
                {
                    //Cria repositório da sequência
                    Sequence Seq = new Sequence();
                    //Obtém campos da sequência.
                    String[] Lines = textseq.Split('\n');
                    int count = 0;
                    foreach (String linha in Lines)
                    {
                        //busca campo locus na linha
                        if(linha.Contains("LOCUS"))
                        {
                            //inicia armazenamento do campo.
                            StringBuilder locusbuilder = new StringBuilder();
                            locusbuilder.Append(linha.Replace("LOCUS","").Trim());
                            //Busca por próximas linhas
                            for (int x = count+1; x < Lines.Length; x++)
                            {
                                //Identifica se ha algum campo iniciando na linha x
                                if (Lines[x].Contains("DEFINITION") || Lines[x].Contains("ACCESSION") || Lines[x].Contains("VERSION") || Lines[x].Contains("KEYWORDS") || Lines[x].Contains("SOURCE") || Lines[x].Contains("ORGANISM") || Lines[x].Contains("REFERENCE") || Lines[x].Contains("AUTHORS") || Lines[x].Contains("TITLE") || Lines[x].Contains("JOURNAL") || Lines[x].Contains("FEATURES") || Lines[x].Contains("BASE COUNT") || Lines[x].Contains("DEFINITION") || Lines[x].Contains("ORIGN") || Lines[x]=="//")
                                {
                                    //finaliza a interação e o campo.
                                    x = Lines.Length;
                                }
                                else
                                {
                                    //Adiciona nova linha ao campo.
                                    locusbuilder.Append(Lines[x].Trim());
                                }
                            }
                            //Armazena o campo no repositório
                            Seq.locus = locusbuilder.ToString();
                        }
                        else if (linha.Contains("DEFINITION"))
                        {
                            //inicia armazenamento do campo.
                            StringBuilder defbuilder = new StringBuilder();
                            defbuilder.Append(linha.Replace("DEFINITION", "").Trim());
                            //Busca por próximas linhas
                            for (int x = count + 1; x < Lines.Length; x++)
                            {
                                //Identifica se ha algum campo iniciando na linha x
                                if (Lines[x].Contains("LOCUS") || Lines[x].Contains("ACCESSION") || Lines[x].Contains("VERSION") || Lines[x].Contains("KEYWORDS") || Lines[x].Contains("SOURCE") || Lines[x].Contains("ORGANISM") || Lines[x].Contains("REFERENCE") || Lines[x].Contains("AUTHORS") || Lines[x].Contains("TITLE") || Lines[x].Contains("JOURNAL") || Lines[x].Contains("FEATURES") || Lines[x].Contains("BASE COUNT") || Lines[x].Contains("DEFINITION") || Lines[x].Contains("ORIGN") || Lines[x] == "//")
                                {
                                    //finaliza a interação e o campo.
                                    x = Lines.Length;
                                }
                                else
                                {
                                    //Adiciona nova linha ao campo.
                                    defbuilder.Append(Lines[x].Trim());
                                }
                            }
                            //Armazena o campo no repositório
                            Seq.definition = defbuilder.ToString();
                            
                            
                        }
                        else if (linha.Contains("VERSION"))
                        {
                            //inicia armazenamento do campo.
                            StringBuilder accbuilder = new StringBuilder();
                            accbuilder.Append(linha.Replace("VERSION", "").Trim());
                            //Busca por próximas linhas
                            for (int x = count + 1; x < Lines.Length; x++)
                            {
                                //Identifica se ha algum campo iniciando na linha x
                                if (Lines[x].Contains("LOCUS") || Lines[x].Contains("ACCESSION") || Lines[x].Contains("DEFINITION") || Lines[x].Contains("KEYWORDS") || Lines[x].Contains("SOURCE") || Lines[x].Contains("ORGANISM") || Lines[x].Contains("REFERENCE") || Lines[x].Contains("AUTHORS") || Lines[x].Contains("TITLE") || Lines[x].Contains("JOURNAL") || Lines[x].Contains("FEATURES") || Lines[x].Contains("BASE COUNT") || Lines[x].Contains("DEFINITION") || Lines[x].Contains("ORIGN") || Lines[x] == "//")
                                {
                                    //finaliza a interação e o campo.
                                    x = Lines.Length;
                                }
                                else
                                {
                                    //Adiciona nova linha ao campo.
                                    accbuilder.Append(Lines[x].Trim());
                                }
                            }
                            //REMOVE O GI(Caso haja)
                            String[] aux = accbuilder.ToString().Trim().Split(' ');
                            //Armazena o campo no repositório
                            Seq.idacession = aux[0];


                        }
                        else if (linha.Contains("SOURCE"))
                        {
                           
                            
                                Seq.idorganism = organismId;
                            


                        }

                        else if (linha.Contains("ORIGIN"))
                        {
                            //inicia armazenamento do campo.
                            StringBuilder seqbuilder = new StringBuilder();
                            seqbuilder.Append(linha.Replace("ORIGIN", "").Trim());
                            //Busca por próximas linhas
                            for (int x = count + 1; x < Lines.Length; x++)
                            {
                                //Identifica se ha algum campo iniciando na linha x
                                if (Lines[x].Contains("LOCUS") || Lines[x].Contains("ACCESSION") || Lines[x].Contains("DEFINITION") || Lines[x].Contains("KEYWORDS") || Lines[x].Contains("VERSION") || Lines[x].Contains("ORGANISM") || Lines[x].Contains("REFERENCE") || Lines[x].Contains("AUTHORS") || Lines[x].Contains("TITLE") || Lines[x].Contains("JOURNAL") || Lines[x].Contains("FEATURES") || Lines[x].Contains("BASE COUNT") || Lines[x].Contains("DEFINITION") || Lines[x].Contains("SOURCE") || Lines[x] == "//")
                                {
                                    //finaliza a interação e o campo.
                                    x = Lines.Length;
                                }
                                else
                                {
                                    //Adiciona nova linha ao campo.
                                    seqbuilder.Append(Lines[x].Trim().Replace(" ", "").Replace("0", "").Replace("1", "").Replace("2", "").Replace("3", "").Replace("4", "").Replace("5", "").Replace("6", "").Replace("7", "").Replace("8", "").Replace("9", ""));
                                }
                            }


                            Seq.sequence = seqbuilder.ToString();
                            Seq.size = Seq.sequence.Length;
                            if (Seq.size > biggerSequence)
                            {
                                biggerSequence = Seq.size;
                                biggerAcession = Seq.idacession;
                            }

                        }

                        count++;
                    }


                    //informa usuário.
                    Seq.iduser_register = usuariologado.id;
                    //Armazena sequência no Banco.
                    try
                    {
                        SequenceDAO.add(Seq);
                        SequenceCount++;
                    }
                    catch(Exception ex)
                    {
                        throw ex;
                    }

                }
                catch (Exception ex)
                {
                    String acession = "ACESSION NOT FOUND";
                    //obtém o acession.
                    String[] linhas = textseq.Split('\n');
                    foreach (String linha2 in linhas)
                    {
                        if (linha2.Contains("VERSION"))
                        {
                            //inicia armazenamento do campo.
                            StringBuilder accbuilder = new StringBuilder();
                            accbuilder.Append(linha2.Replace("VERSION", "").Trim());
                            //REMOVE O GI(Caso haja)
                            String[] aux = accbuilder.ToString().Trim().Split(' ');
                            //Armazena o campo no repositório
                            acession = aux[0];
                        }
                    }
                    String newMessage = "Unknow Error";
                    if (ex.Message.Substring(0, 15) == "Duplicate entry")
                    {
                        newMessage = "Duplicate entry";
                    }
                    else
                    {
                        newMessage = ex.Message;
                    }
                    String[] detail = new String[3];
                    detail[0] = "ACESSION: " + acession+" - ";
                    detail[1] = "RESULT: " + "FAIL" + " - ";
                    detail[2] = "MESSAGE: " + newMessage + " | ";
                    //Armazena o detail no report.
                    report.Add(detail);
                    ErrorCount++;

                }
               
                //LimpaTextSeq
                textseq = "";
            }
        }
        reader.Close();
        File.Delete(FileName);
        //envia a mensagem.
        Message msg = new Message();
        msg.senduserid = usuariologado.id;
        msg.touserid = usuariologado.id;
        msg.title = "Job: "+jobcode;
        StringBuilder builder = new StringBuilder();
        String elapsed = DateTime.Now.Subtract(Starttime).ToString(@"hh\:mm\:ss\.FF"); ;
        builder.Append( "Job finished in "+ elapsed+ ". \r\n" + SequenceCount.ToString() + " Sequences were added. \r\n"+"Bigger Sequence: "+biggerAcession+" - "+biggerSequence.ToString()+"\r\n" + ErrorCount.ToString() + " Errors found.\r\n \r\n");
        if (report.Count > 0)
        {
            builder.Append("ERROR REPORT \r\n \r\n");
        }
        foreach (String[] details in report)
        {
            
            builder.Append( details[0]);
            builder.Append( details[1]);
            builder.Append( details[2]);
            builder.Append(  " \r\n");
        }
        msg.message = builder.ToString();
        MessageDAO.sendMessage(msg);


    }



 
}